// <copyright file="CavernGenerator.UniqueProperties.cs" company="TenneySoftware">
// Copyright (c) 2009 All Right Reserved
// </copyright>
// <author>Robert Tenney</author>
// <email>rob10e@yahoo.com</email>
// <date>April 2009</date>
// <summary>Cavern style level generator module.</summary>

// License:

// Product: RPGRoguelikeEngine .Net
// Author: Robert N. Tenney
// Copyright: April 2009

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation version 2
// of the License.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

// This license covers all source code, binaries, and other materials related to this project
// unless specifically stated otherwise.

using System;
using System.Drawing;
using TenneySoftware.Engine;

namespace TenneySoftware.LevelGenerator.CavernGenerator {
    /// <content>
    /// This file contains the Unqie (Not defined within ILevelGenerator interface) properties for the generator.
    /// </content>
    public partial class Cavern {
        /// <summary>
        /// Gets or sets a value between 0 - 100 that represents the density of of the level. The higher the number, the
        /// more dense it will be. A value of 100 equals 100 percent density.
        /// </summary>
        /// <value>
        /// The density of the level.</value>
        public int Density {
            get {
                return this.cellAutomata.Density;
            }
            
            set {
                this.cellAutomata.Density = value;
                this.SetName("Custom");
            }
        }
        
        /// <summary>
        /// Gets or sets the number of iterations.
        /// </summary>
        /// <value>
        /// The number of iterations.
        /// </value>
        public int IterationsMutationFill {
            get {
                return this.cellAutomata.IterationsMutationFill;
            }
            
            set {
                this.cellAutomata.IterationsMutationFill = value;
                this.SetName("Custom");
            }
        }

        /// <summary>
        /// Gets or sets the iterations with cellular mutation only.
        /// </summary>
        /// <value>
        /// The iterations with cellular mutations only.
        /// </value>
        public int IterationsMutationOnly {
            get {
                return this.cellAutomata.IterationsMutationOnly;
            }
            
            set {
                this.cellAutomata.IterationsMutationOnly = value;
                this.SetName("Custom");
            }
        }

        /// <summary>
        /// Gets or sets the distance from center point to check for filling.
        /// </summary>
        /// <value>
        /// The distance from center point to check for filling.
        /// </value>
        public int FillSearchArea {
            get {
                return this.cellAutomata.FillSearchArea;
            }
            
            set {
                this.cellAutomata.FillSearchArea = value;
                this.SetName("Custom");
            }
        }

        /// <summary>
        /// Gets or sets the number of walls needed to connect to the center point for
        /// it to be classified as a wall.
        /// </summary>
        /// <value>
        /// The number of walls needed to connect to the center point for
        /// it to be classified as a wall.
        /// </value>
        public int CountForValidWalls {
            get {
                return this.cellAutomata.CountForValidWalls;
            }
            
            set {
                this.cellAutomata.CountForValidWalls = value;
                this.SetName("Custom");
            }
        }

        /// <summary>
        /// Gets or sets the minimum number of wall tiles needed to fill an area.
        /// </summary>
        /// <value>
        /// The minimum number of wall tiles needed to fill an area.
        /// </value>
        public int CountForValidWallsForFill {
            get {
                return this.cellAutomata.CountForValidWallsForFill;
            }
            
            set {
                this.cellAutomata.CountForValidWallsForFill = value;
                this.SetName("Custom");
            }
        }

        /// <summary>
        /// Retrieves a list of properties that are unique to this generator and not to any other.
        /// </summary>
        /// <returns>An array of GeneratorData objects with information about the unique properties within this generator.</returns>
        public GeneratorData[] GetUniquePropertyInformation() {
            GeneratorData[] result = new GeneratorData[7];
            result[0] = new GeneratorData(0, "Size", "Sets the size of the level to generate.", new string[] { typeof(Size).ToString() });
            result[1] = new GeneratorData(1, "CountForValidWalls", "Sets the number of walls within the area that are needed for the center point to be/stay a wall.", new string[] { typeof(int).ToString() });
            result[2] = new GeneratorData(2, "CountForValidWallsForFill", "Sets the number of walls within the fill area that are needed for the center point to be/stay a wall during a fill iteration.", new string[] { typeof(int).ToString() });
            result[3] = new GeneratorData(3, "IterationsMutationFill", "Sets the number of iterations to run for mutation AND filling.", new string[] { typeof(int).ToString() });
            result[4] = new GeneratorData(4, "IterationsMutationOnly", "Sets the number of iterations to run for mutation only, no filling.", new string[] { typeof(int).ToString() });
            result[5] = new GeneratorData(5, "FillSearchArea", "Sets the area around a point to scan for wall tiles to determine if filling is needed.", new string[] { typeof(int).ToString() });
            result[6] = new GeneratorData(6, "Density", "Sets the initial density of the level.", new string[] { typeof(int).ToString() });
            return result;
        }

        /// <summary>
        /// Passes parameters to unique properties within this generator through the ILevelSettings interface. Properties
        /// available are:
        /// 0 - SetSize - Size
        /// 1 - CountForValidWalls - int
        /// 2 - CountForValidWallsForFill - int
        /// 3 - IterationsMutationFill - int
        /// 4 - IterationsMutationOnly - int
        /// 5 - FillSearchArea - int
        /// 6 - Density - int
        /// options usage: new object[][]{new object[]{0, new Size(64, 64)}}
        /// To set the level size to 64 by 64.
        /// </summary>
        /// <param name="options">Jagged array of objects with the property code at the first position, and the value
        /// to pass in the second position.</param>
        public void SetUniqueProperties(object[][] options) {
            if (options.GetLength(0) > 7) {
                throw new ArgumentException("Too many options in array. Recheck your options.");
            }
            
            foreach (object[] args in options) {
                switch ((int)args[0]) {
                    case 0:
                        if (args[1] is Size) {
                            this.SetSize((Size)args[1]);
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(Size).ToString() + " type to set level size.");
                        }
                        
                        break;
                    case 1:
                        if (args[1] is int) {
                            this.CountForValidWalls = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the count for valid walls.");
                        }
                        
                        break;
                    case 2:
                        if (args[1] is int) {
                            this.CountForValidWallsForFill = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the count for valid walls for fill iterations only.");
                        }
                        
                        break;
                    case 3:
                        if (args[1] is int) {
                            this.IterationsMutationFill = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the iterations for mutations and fill.");
                        }
                        
                        break;
                    case 4:
                        if (args[1] is int) {
                            this.IterationsMutationOnly = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the iterations for mutations only.");
                        }
                        
                        break;
                    case 5:
                        if (args[1] is int) {
                            this.FillSearchArea = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the area for fill search.");
                        }
                        
                        break;
                    case 6:
                        if (args[1] is int) {
                            this.Density = (int)args[1];
                        } else {
                            throw new ArgumentException("Option needs to be a "
                                                        + typeof(int).ToString() + " type to set the initial density for level.");
                        }
                        
                        break;
                }
            }
        }
    }
}